package com.sky.sky_server.interceptor;

import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.sky.sky_common.config.JwtProperties;
import com.sky.sky_common.constant.JwtRoleConstant;
import com.sky.sky_common.context.BaseContext;
import com.sky.sky_common.util.JwtService;

import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * JwtTokenAdminInterceptor类用于处理管理员相关的JWT令牌拦截逻辑
 * 该类实现了HandlerInterceptor接口，用于在请求处理前进行JWT令牌验证
 */
@Component
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    /**
     * JWT服务类，用于处理JWT令牌的相关操作
     */
    private final JwtService jwtService;
    /**
     * JWT属性配置类，包含JWT相关的配置信息
     */
    private final JwtProperties jwtProperties;

    /**
     * 构造函数，通过依赖注入方式初始化JWT服务和属性配置
     * @param jwtService JWT服务类
     * @param jwtProperties JWT属性配置类
     */
    public JwtTokenAdminInterceptor(JwtService jwtService, JwtProperties jwtProperties){
        this.jwtService = jwtService;
        this.jwtProperties = jwtProperties;
    }

    public boolean preHandle1(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 从请求头中获取JWT令牌
        String token = request.getHeader(jwtProperties.getAdminHeader());
        if((token == null) || token.isBlank()){
            // 如果没有携带JWT令牌，则去Authorization头中获取
            // 有些前端框架和第三方SDK会默认将JWT令牌放在Authorization头中
            // 不写也行，本项目默认放在请求头 token 中
            String auth = request.getHeader("Authorization");
            if(auth != null && auth.startsWith("Bearer ")){
                token = auth.substring(7);
            }
        }

        // 如果获取到的token为空，则返回401状态码
        if(token == null || token.isBlank()){
            response.setStatus(401);
            response.getWriter().write("没有携带有效token");
            return false;
        }

        // 解析JWT令牌
        try {
            Claims claims = jwtService.parseJwtToken(token, JwtRoleConstant.ADMIN);
            // 将用户信息放入请求属性（或 ThreadLocal / SecurityContext）
            
            // todo claims 键值对 需要与查询结果一致
            request.setAttribute("username", claims.get("username"));
            request.setAttribute("id", claims.get("id"));
            request.setAttribute("roles", claims.get("roles"));
            return true;
        }catch(Exception e){
            // 解析失败，返回401状态码
            response.setStatus(401);
            response.getWriter().write("invalid or expired token, please login again");
            return false;
        }
    }

    /**
     * 直接将异常抛出统一交给全局处理类处理，并返回统一的结果
     */
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request,@NonNull  HttpServletResponse response,@NonNull  Object handler) {
        String token = request.getHeader(jwtProperties.getAdminHeader());
        if (token == null || token.isBlank()) {
            String auth = request.getHeader("Authorization");
            if (auth != null && auth.startsWith("Bearer ")) {
                token = auth.substring(7);
            }
        }

        if (token == null || token.isBlank()) {
            // 没有 token：抛异常，让全局异常处理
            throw new io.jsonwebtoken.JwtException("Missing token");
        }

        Claims claims = jwtService.parseJwtToken(token, JwtRoleConstant.ADMIN); // 解析失败会抛 JwtException
        // todo claims 键值对 需要与查询结果一致
        request.setAttribute("username", claims.get("username"));
        request.setAttribute("roles", claims.get("roles"));
        // tag 在拦截器中定义，后面的remove语句应该定义在哪里？还是每次请求都覆盖，定义在postHandle中
        BaseContext.setCurrentId(Long.parseLong(claims.get("id").toString()));
        return true;
    }

    public void postHandle(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler,@Nullable ModelAndView modelAndView) throws Exception {
        BaseContext.remove();
   }

}
